﻿package net.jmp0.toast.levels 
{
	import flash.events.Event;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	import net.jmp0.toast.entities.effects.LevelCompleteOverlay;
	import punk.util.Input;
	/**
	 * ...
	 * @author Thodd
	 */
	public class LevelTracker
	{
		//
		private static var instance:LevelTracker;
		
		//This List and the corresponding pointer tell me which level the player is currently in
		private static var allLevelsAsXMLFiles:Array = new Array();
		private static var allLevels:Array = new Array();
		private static var currentLevel:int = -1;
		
		//Embedding all levelfiles and adding them to the static levelarray
		//[Embed(source = '../res/xml/Level1.xml', mimeType = "application/octet-stream")] public static const LevelOneXMLFile:Class;
		//allLevelsAsXMLFiles[0] = LevelOneXMLFile;
		/*
		[Embed(source = '../res/xml/TestLevel.xml', mimeType = "application/octet-stream")] public static const TestLevelXMLFile:Class;
		allLevelsAsXMLFiles[0] = TestLevelXMLFile;
		[Embed(source = '../res/xml/BananaTest.xml', mimeType = "application/octet-stream")] public static const BananaTestXMLFile:Class;
		allLevelsAsXMLFiles[1] = BananaTestXMLFile;
		[Embed(source = '../res/xml/ToasterTest.xml', mimeType = "application/octet-stream")] public static const ToasterTestXMLFile:Class;
		allLevelsAsXMLFiles[2] = ToasterTestXMLFile;
		[Embed(source = '../res/xml/TeleporterTest.xml', mimeType = "application/octet-stream")] public static const TeleporterTestXMLFile:Class;
		allLevelsAsXMLFiles[3] = TeleporterTestXMLFile;
		[Embed(source = '../res/xml/KeyTest.xml', mimeType = "application/octet-stream")] public static const KeyTestXMLFile:Class;
		allLevelsAsXMLFiles[4] = KeyTestXMLFile;
		[Embed(source = '../res/xml/PushableTest.xml', mimeType = "application/octet-stream")] public static const PushableTestXMLFile:Class;
		allLevelsAsXMLFiles[5] = PushableTestXMLFile;
		[Embed(source = '../res/xml/OrangeTest.xml', mimeType = "application/octet-stream")] public static const OrangeTestXMLFile:Class;
		allLevelsAsXMLFiles[6] = OrangeTestXMLFile;
		[Embed(source = '../res/xml/SomeTestLevel.xml', mimeType = "application/octet-stream")] public static const SomeTestXMLFile:Class;
		allLevelsAsXMLFiles[7] = SomeTestXMLFile;
		*/
		
		[Embed(source = '../res/xml/01_thefirst.xml', mimeType = "application/octet-stream")] public static const Level_01_XMLFile:Class;
		allLevelsAsXMLFiles[0] = Level_01_XMLFile;
		[Embed(source = '../res/xml/02_thesecond.xml', mimeType = "application/octet-stream")] public static const Level_02_XMLFile:Class;
		allLevelsAsXMLFiles[1] = Level_02_XMLFile;
		[Embed(source = '../res/xml/03_thethird.xml', mimeType = "application/octet-stream")] public static const Level_03_XMLFile:Class;
		allLevelsAsXMLFiles[2] = Level_03_XMLFile;
		[Embed(source = '../res/xml/04_yaybananas.xml', mimeType = "application/octet-stream")] public static const Yaybananas_XMLFile:Class;
		allLevelsAsXMLFiles[3] = Yaybananas_XMLFile;
		[Embed(source = '../res/xml/05_morebananas.xml', mimeType = "application/octet-stream")] public static const Morebananas_XMLFile:Class;
		allLevelsAsXMLFiles[4] = Morebananas_XMLFile;
		[Embed(source = '../res/xml/06_lookseasy.xml', mimeType = "application/octet-stream")] public static const lookseasy_XMLFile:Class;
		allLevelsAsXMLFiles[5] = lookseasy_XMLFile;
		[Embed(source = '../res/xml/07_tricky.xml', mimeType = "application/octet-stream")] public static const tricky_XMLFile:Class;
		allLevelsAsXMLFiles[6] = tricky_XMLFile;
		[Embed(source = '../res/xml/08_hereandthere.xml', mimeType = "application/octet-stream")] public static const hereandthere_XMLFile:Class;
		allLevelsAsXMLFiles[7] = hereandthere_XMLFile;
		[Embed(source = '../res/xml/09_dontwasteit.xml', mimeType = "application/octet-stream")] public static const dontwasteit_XMLFile:Class;
		allLevelsAsXMLFiles[8] = dontwasteit_XMLFile;
		[Embed(source = '../res/xml/10_frenchtoast.xml', mimeType = "application/octet-stream")] public static const frenchtoast_XMLFile:Class;
		allLevelsAsXMLFiles[9] = frenchtoast_XMLFile;
		[Embed(source = '../res/xml/11_confusing.xml', mimeType = "application/octet-stream")] public static const confusing_XMLFile:Class;
		allLevelsAsXMLFiles[10] = confusing_XMLFile;
		
		//This variable holds a reference to the currently displayed "LevelCompleteOverlay"
		//a message box containing informations about the next level
		public static var currentOverlay:LevelCompleteOverlay = null;
		
		/**
		 * When the LevelTracker is constructed all XML Files are transformed to XML objects
		 */
		public function LevelTracker() {
			
			for (var i:int = 0; i < allLevelsAsXMLFiles.length; i++) {
				var file:ByteArray = new allLevelsAsXMLFiles[i];
				var str:String = file.readUTFBytes(file.length);
				var xmlData:XML = new XML(str);
				
				allLevels.push(xmlData);
			}
			allLevelsAsXMLFiles = null;
			
		}
		
		/**
		 * Sets the LevelList of the LevelTracker, the level iterator is reset
		 * @param	levelList An Array containing the level XML data
		 */
		public function setLevelList(levelList:Array):void {
			allLevels = null;
			allLevels = levelList;
			currentLevel = -1;
		}
		
		
		/**
		 * returns the single instance of the LevelTracker
		 * @return the instance
		 */
		public static function getInstance():LevelTracker {
			if (instance == null) {
				//set to -1 because when we call next() for the first time we want to get the Level at position 0
				currentLevel = -1;
				instance = new LevelTracker();
			}
			return instance;
		}
		
		/**
		 * Delivers the next level following the current one or the first level if we reached the last level
		 * and increments the level pointer
		 * This method doesn't switch the level for you, it only returns the next level in line as a XML object
		 * 
		 * @return the next level as a XML file
		 */
		public function next():XML {
			currentLevel += 1;
			if(currentLevel < allLevels.length){
				return allLevels[currentLevel];
			}else {
				trace("you win all");
				currentLevel = 0;
				return allLevels[0]; //TODO: Go to "you win all" screen
			}
		}
		
		/**
		 * Returns if there are still some levels left to play
		 * @return mh yeah look above...
		 */
		public function hasNext():Boolean {
			return (currentLevel < allLevels.length);
		}
		
		
		/**
		 * Returns a specific level represented by it's position in the global levellist
		 * @param	i The position of the level you want to get
		 * @return a reference to a XML file containing the level information, this is used by GameLevel
		 * @see GameLevel
		 */
		public function getLevel(i:int):XML {
			if(i <= allLevels.length){
				return allLevels[i];
			}else {
				return allLevels[0];
			}
		}
		
		/**
		 * Returns the number of the currentLevel
		 * @return the iterator position
		 */
		public function getCurrentLevelNumber():int {
			return currentLevel;
		}
		
		
		/**
		 * Finds a level by the password associated with the level
		 * @param	pw The password used to find the level
		 * @return a XML object containing the level information OR null if none was found
		 */
		public function findLevelByPassword(pw:String):XML{
			for (var i:int = 0; i < allLevels.length; i++) {
				trace(allLevels[i].@password);
				
				if (allLevels[i].@password == pw) {
					currentLevel = i; //ok this sucks, the currentLevel is set before anything happens, can become a problem :(
					return allLevels[i];
				}
			}
			return null;
		}
		
		
		
		/**
		 * Sets the currentLevel pointer to a specific position, this method doesn't switch to that level though...
		 * It's more like a debug function
		 * 
		 * @param	i the new position of the level pointer
		 * @return the XML the level pointer points to
		 */
		public function setCurrentLevel(i:int):XML {
			if (i <= allLevels.length) {
				currentLevel = i;
			}
			return allLevels[currentLevel];
		}
		
		
		/**
		 * This method actually starts the level you handed over to it
		 * @param	xmlData the level you want to switch to
		 */
		public function switchToLevel(xmlData:XML):void {
			currentOverlay = null;

			//ok now this sucks, but otherwise you can see a small glimpse of an orange messagebox
			//maybe because there is single frame slipping through between levelchanging?
			//anyway, reseting the Mous flags solves this
			Input.mouseDown = false;
			Input.mousePressed = false;
			
			FP.goto = new GameLevel(xmlData);
		}
		
		
		/**
		 * Initialises a level change by displaying a messagebox with informations about the next level
		 * @param	xmlData The level which will be loaded by this function
		 * @param	msg a String that is shown inside the messagebox
		 */
		public function switchToLevelWithMessage(xmlData:XML, msg:String = "", title:String = null):void {
			trace("level to be loaded : " + xmlData.@title);
			currentOverlay = new LevelCompleteOverlay(xmlData, msg, switchToLevel);
			if (title != null) {
				currentOverlay.speechTitle.text = title;
			}
		}
		
		
	}

}